/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.monkey.mvn.plugin;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.springframework.util.FileCopyUtils;

/**
 *
 * @goal create-mar
 * @author edoardo
 */
public class MarManager extends AbstractMojo {

    /**
     * @parameter
     */
    private String destinationDir;
    /**
     * Location of the file.
     * @parameter expression="${project.build.directory}"
     * @required
     */
    private File outputDirectory  ;
    /**
     * @paramter
     */
    private File[] springFiles = new File[0];
    /**
     * @parameter
     */
    private File[] etcFiles=new File[0];
    /**
     * @parameter
     */
    private File localRepository = DEFAULT_LOCAL_REPOSITORY;
    private static final File DEFAULT_LOCAL_REPOSITORY = new File(new StringBuilder(System.getProperty("user.home")).append(File.separator).append(".m2").append(File.separator).append("repository").append(File.separator).toString());

    public void execute() throws MojoExecutionException, MojoFailureException {
        {
            File file = null;
            try {
                getLog().info(new StringBuffer("Creating tree into " + getDestinationDir()));
                if (!getDestinationDir().endsWith(File.separator)) {
                    setDestinationDir(destinationDir + File.separator);
                }
                File springDir = createDir(destinationDir + "spring");
                getLog().info(new StringBuffer("Create dir " + springDir));
                File libsDir = createDir(destinationDir + "libs");
                getLog().info(new StringBuffer("Create dir " + libsDir));
                File etcDir = createDir(destinationDir + "etc");
                getLog().info(new StringBuffer("Create dir " + etcDir));
                //File classes = createDir(destinationDir + "classes");
                MavenProject mavenPrj = (MavenProject) getPluginContext().get("project");
                String groupId = mavenPrj.getGroupId();
                String artifactId = mavenPrj.getArtifactId();
                String version = mavenPrj.getVersion();
                String packaging = mavenPrj.getPackaging();
                String fileName = getArtifactFileName(artifactId, version, packaging);
                String path = getPathDependency(groupId);
                file = getFile(path, artifactId, version, fileName);
                List<Dependency> listDependencies = mavenPrj.getDependencies();
                for (Iterator<Dependency> it = listDependencies.iterator(); it.hasNext();) {
                    Dependency dependency = it.next();
                    File in = getFile(getPathDependency(dependency.getGroupId()), dependency.getArtifactId(), dependency.getVersion(), getArtifactFileName(dependency.getArtifactId(), dependency.getVersion(), "jar"));
                    FileCopyUtils.copy(in, new File(libsDir + File.separator + in.getName()));
                    getLog().info(new StringBuffer("Copyed dependency  " + in.getAbsolutePath()));
                }
                FileCopyUtils.copy(file, new File(libsDir + File.separator + file.getName()));
                getLog().info(new StringBuffer("Copyed file  " + file.getAbsolutePath()));
                copyFiles(springFiles, springDir);
                copyFiles(etcFiles, etcDir);

                //inizio a creare il mar una volta copiati tutti file necessari

                JarOutputStream out = new JarOutputStream(new FileOutputStream(outputDirectory + File.separator + getArtifactFileName(mavenPrj.getArtifactId(), mavenPrj.getVersion(), "mar")));


                createMar(libsDir.listFiles(), libsDir.getName(), out);
                createMar(springDir.listFiles(), springDir.getName(), out);
                createMar(etcDir.listFiles(), etcDir.getName(), out);

                out.close();


            } catch (IOException ex) {
                Logger.getLogger(MarManager.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }

    private void createMar(File[] fileList, String srcDir, JarOutputStream out) throws IOException {
        for (File aJar : fileList) {
            if (aJar.isDirectory()) {
                createMar(aJar.listFiles(),srcDir+File.separator+aJar.getName(),out);
            } else {
                JarEntry e = new JarEntry(srcDir + File.separator + aJar.getName());
                out.putNextEntry(e);
                InputStream in = new FileInputStream(aJar.getAbsolutePath());
                byte[] buff = new byte[4096];
                int ch = 0;
                while ((ch = in.read(buff)) > 0) {
                    out.write(buff, 0, ch);
                }
            }
        }
    }

    private void copyFiles(File[] fileList, File destDir) throws IOException {
        if (fileList != null) {
            for (File aFile : fileList) {
                FileCopyUtils.copy(aFile, new File(destDir + File.separator + aFile.getName()));
                getLog().info(new StringBuffer("Copyed file  " + aFile.getAbsolutePath()));
            }
        }
    }

    private String getArtifactFileName(String artifactId, String version, String packaging) {
        String fileName = artifactId + "-" + version + "." + packaging;
        return fileName;
    }

    private File getFile(String path, String artifactId, String version, String fileName) throws FileNotFoundException {
        File file = new File(localRepository + File.separator + path + File.separator + artifactId + File.separator + version + File.separator + fileName);
        return file;
    }

    private String getPathDependency(String groupId) {
        String path = groupId.replace(".", File.separator);
        return path;
    }

    private File createDir(String name) {
        File aDir = new File(name);
        System.out.println("aDir = " + aDir);
        if (!aDir.exists()) {
            aDir.mkdir();
        }
        return aDir;
    }

    public File[] getEtcFiles() {
        return etcFiles;
    }

    public void setEtcFiles(File[] etcFiles) {
        this.etcFiles = etcFiles;
    }

    public File[] getSpringFiles() {
        return springFiles;
    }

    public void setSpringFiles(File[] springFiles) {
        this.springFiles = springFiles;
    }

    public String getDestinationDir() {
        return destinationDir;
    }

    public void setDestinationDir(String destinationDir) {
        this.destinationDir = destinationDir;
    }

    public File getOutputDirectory() {
        return outputDirectory;
    }

    public void setOutputDirectory(File outputDirectory) {
        this.outputDirectory = outputDirectory;
    }

    public File getLocalRepository() {
        return localRepository;
    }

    public void setLocalRepository(File localRepository) {
        this.localRepository = localRepository;
    }
}
